package simulatie.models;

import java.awt.Color;
import java.util.Hashtable;
import javax.media.opengl.GL;
import javax.vecmath.TexCoord2f;
import javax.vecmath.Vector3f;

/**
 * De abstracte model klasse<br>
 * implements Cloneable
 * @author TetraCON
 *
 */public abstract class Model implements Cloneable{
	protected Hashtable<Integer,FaceIndex> faceIndicies;
	protected Hashtable<Integer,Vector3f> vertices;
	protected Hashtable<Integer,TexCoord2f> texCoords;
	protected Hashtable<Integer,Vector3f> normals;
	protected Color color;
	protected Vector3f position;
	protected Vector3f scale;
	
	protected GL gl;
	protected Hashtable<Integer,Rotation> rotations;
	
/**
 * Geeft elk model een Hashtable voor rotations mee
 */
	protected Model() {
		rotations = new Hashtable<Integer,Rotation>();
	}
	
	public abstract void displayModel(GL gl);	
	protected abstract void setFaceIndicies();
	protected abstract void setTexCoords();
	protected abstract void setNormals();
	protected abstract void setVertices();
	
/**
 * Stel de positie van het Model in
 * @param pos - positie als Vector3f
 */	
	public void setPosition(Vector3f pos) {
		this.position = pos;
	}
	
/**
 * Stel de positie van het Model in 
 * @param x - X-positie als float
 * @param y - Y-positie als float
 * @param z - Z-positie als float
 */
	public void setPosition(float x, float y, float z) {
		this.position = new Vector3f(x,y,z);
	}

/**
 * Voeg een rotatie toen aan het model.
 * @param rot - hoeveelste rotatie
 * @param rotation - rotatie als vector3f
 */	
	public void addRotation(float rot, Vector3f rotation) {
		rotations.put(rotations.size(), new Rotation(rot, rotation));
	}
	
/**
 * Voeg een rotatie toen aan het model.
 * @param rot - hoeveelste rotatie
 * @param x - X-rotatie als float
 * @param y - Y-rotatie als float
 * @param z - Z-rotatie als float
 */	
	public void addRotation(float rot, float x, float y, float z) {
		rotations.put(rotations.size(), new Rotation(rot,new Vector3f(x,y,z)));
	}
	
	public void removeLastRotation() {
		if (!rotations.isEmpty()) {
			rotations.remove(rotations.size()-1);
		}
	}
	
/**
 * Stel de schaal van het Model in
 * @param scale - Schaal als Vector3f
 */	
	public void setScale(Vector3f scale) {
		this.scale = scale;
	}

/**
 * Stel de schaal van het Model in
 * @param x - Schaal in de X-richting
 * @param y - Schaal in de Y-richting
 * @param z - Schaal in de Z-richting
 */
	public void setScale(float x, float y, float z) {
		this.scale = new Vector3f(x,y,z);
	}

/**
 * Vraag de positie van het Model
 * @return - Positie als Vector3f
 */	public Vector3f getPosition() {
		return position;
	}
	
/**
 * Stel de kleur van het Model in 
 * @param r Hoeveelheid Rood
 * @param g Hoeveelheid Groen
 * @param b Hoeveelheid Blauw
 */	
 	public void setColor(int r, int g, int b) {
		this.color = new Color(r,g,b);
	}
	
/**
 * Teken het model met alle meegegeven eigenschappen
 */
 	protected void drawVertices() {
		gl.glPushMatrix();
		gl.glTranslatef(position.getX(), position.getY(), position.getZ());
		gl.glRotatef(-90,1,0,0);
		
		for (int i = 0; i < rotations.size(); i++) {
			Rotation rot = rotations.get(i);
			gl.glRotatef(rot.getAngle(),rot.getRotxyz().getX(),rot.getRotxyz().getY(), rot.getRotxyz().getZ());
		}
		
		gl.glScalef(scale.getX(), scale.getY(), scale.getZ());
		gl.glBegin(GL.GL_TRIANGLES);
		float[] colors = color.getColorComponents(null);
		gl.glColor3f(colors[0], colors[1], colors[2]);
			
		for (int i = 0; i < faceIndicies.size(); i++) {
			for (int j = 0; j < 3; j++) {
				int vi = faceIndicies.get(i).get(j);
		        int ni=faceIndicies.get(i).get(j+3);//Normal index
		        int ti=faceIndicies.get(i).get(j+6);//Texture index
		        gl.glNormal3f (normals.get(ni).getX(),normals.get(ni).getY(),normals.get(ni).getZ());
		        gl.glTexCoord2f(texCoords.get(ti).getX(),texCoords.get(ti).getY());
		        gl.glVertex3f (vertices.get(vi).getX(),vertices.get(vi).getY(),vertices.get(vi).getZ());
			}
		}
		
		gl.glEnd();
		gl.glPopMatrix();
	}
	
/**
 * Clone een Object
 */	
 	public Object clone() {
		try {
			return super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
			return null;
		}
	}
 	
	public void init() {
		rotations = new Hashtable<Integer,Rotation>();
	}
}
